home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / batchut / setenv13.zip / SETENVS.C < prev   
Text File  |  1989-09-28  |  5KB  |  198 lines

  1. /* subroutine to put a value string into an environment symbol.
  2.    Uses the controling command.com environment, not the programs.
  3.    This means that the env variable is set so other routines in
  4.    a .BAT file may use it.
  5.  
  6.    call:  settheenv (char * symbol, char * val);
  7.    symbol is an asciiz string containing the env variable name,
  8.    val    is an asciiz string containing the value to assign to this vbl.
  9.  
  10.    returns: 0 = OK,
  11.         1 = failure.
  12.    failure is not unlikely.  The env block may be full.  Or on some
  13.    systems the env block might not be found
  14. */
  15.  
  16.  
  17. #include <stdio.h>
  18. #include <dos.h>
  19. #include <string.h>
  20. #include <stdlib.h>
  21.  
  22. typedef struct {
  23.     char fill1[0x0A];
  24.     int *prev_term_handler;
  25.     int *prev_ctrl_c;
  26.     int *prev_crit_error;
  27.     char fill2[0x16];
  28.     int  envir_seg;
  29.     } psp;
  30.  
  31. typedef struct {
  32.     char  type;
  33.     int   psp_segment;
  34.     int   num_segments;
  35.         char  fill[11];
  36.         char  arena_data;
  37.     } arena;
  38.  
  39.  
  40. #define NORMAL_ATYPE 0x4D
  41. #define LAST_ATYPE   0x5A
  42.  
  43.  
  44. static arena * get_next_arena (arena * ap) {
  45.     return( MK_FP( FP_SEG(ap)+1+ap->num_segments, 0) );
  46. }
  47.  
  48. /* returns 0 if passed pointer is to an arena, else returns 1 */
  49. int is_valid_arena (arena * ap) {
  50.     arena * ap1;
  51.     if (   ap->type == NORMAL_ATYPE  &&
  52.           (ap1=get_next_arena(ap))->type == NORMAL_ATYPE  &&
  53.           ( (ap1=get_next_arena(ap1))->type == NORMAL_ATYPE  ||
  54.          ap1->type == LAST_ATYPE) )
  55.             return(0);
  56.     return (1);
  57. }
  58.  
  59.  
  60. static arena * get_first_arena () {
  61. /* return pointer to the first arena.
  62.  * scan memory for a 0x4D on a segment start,
  63.  * see if this points to another two levels of arena
  64.  */
  65.         arena * ap, * ap1;
  66.     int * temp;
  67.         int segment;
  68.         for (segment=0; segment<_CS;  segment++) {
  69.         ap = MK_FP(segment, 0);
  70.         if ( is_valid_arena (ap) == 0)  return (ap);
  71.     }
  72.     return(NULL);
  73. } /* end get_first_arena */
  74.  
  75.  
  76. static int is_valid_env (char * ad, int num_segs) {
  77.     char * base_ad;
  78.     base_ad = ad;
  79.     while ( (*ad) && (((ad-base_ad)>>4) < num_segs) ) {
  80.         if (strnicmp(ad, "COMSPEC=", 8)==0)  return(0);
  81.         ad += strlen(ad) + 1;
  82.     }
  83.     return (1);
  84. }
  85.  
  86.  
  87. static arena * get_arena_of_environment () {
  88. /* to get the arena of first environment block:
  89.    First get segment of COMMAND.COM from segment of previous critical err code.
  90.    Then scan all the arenas for an environment block with a matching PSP
  91.    segment */
  92.  
  93. arena * ap;
  94. psp   * pspp, * pspc;
  95. unsigned int i, ccseg;
  96.  
  97. /* set pspp to psp of this program */
  98. pspp = MK_FP(_psp,0);
  99.  
  100. #ifdef DEBUG
  101. printf("prog psp=%p\n",pspp);
  102. #endif
  103.  
  104. /* set pspc to psp of COMMAND.COM, back up a bit to get it if needed */
  105. ccseg = FP_SEG (pspp->prev_crit_error);
  106. if ( (i=ccseg-32) < 60)  i=60;
  107.  
  108. while (ccseg>i) {
  109.     pspc = MK_FP (ccseg, 0);
  110.     if ( is_valid_arena((arena *) pspc) == 0)  goto L1;
  111.     ccseg--;
  112. }
  113. return (NULL);
  114.  
  115. L1: pspc = MK_FP (++ccseg, 0);
  116. #ifdef DEBUG
  117. printf("comm.com=%p\n",pspc);
  118. #endif
  119.  
  120. /* first see if env seg in command.com points to valid env block
  121.    if env seg is in a valid arena, then arena must point to this command.com
  122.    else assume env block is fabricated like for 4DOS, use 128 bytes */
  123.  
  124. ap = MK_FP (pspc->envir_seg-1, 0);
  125. i  = ap->num_segments;
  126.  
  127. if (is_valid_arena (ap) == 0) {
  128.     if (ap->psp_segment != FP_SEG(pspc))  goto L2;
  129. } else {
  130.     i = 9;
  131. }
  132.  
  133. if ( is_valid_env (&ap->arena_data, i) == 0 )
  134.     return (ap);
  135.  
  136. /* command.com did not so point, search thru all env blocks */
  137.  
  138. L2:
  139. if ( (ap=get_first_arena()) != NULL ) {
  140.     while (ap->type != LAST_ATYPE) {
  141. #ifdef DEBUG
  142.         printf("%p\n",ap);
  143. #endif
  144.         if (ap->psp_segment == FP_SEG(pspc) &&
  145.             is_valid_env (&ap->arena_data, ap->num_segments)==0 )
  146.             return (ap);
  147.  
  148.         ap = get_next_arena(ap);
  149.     }
  150. } return(NULL);
  151. }  /* end get_arena_of_environment */
  152.  
  153. /*****************************************************************************/
  154.  
  155. char settheenv(char * symbol, char * val) {
  156. int total_size,
  157.     needed_size=0,
  158.     strlength;
  159. char * sp, *op, *envir;
  160. char symb_len=strlen(symbol);
  161. char found=0;
  162. arena * ap;
  163.  
  164. strupr(symbol);
  165.  
  166. /* first, can COMMAND.COM's envir block be found ? */
  167. if ( (ap=get_arena_of_environment()) == NULL)
  168.     return(1);
  169.  
  170. /* search to end of the envir block, get sizes */
  171. total_size = 16 * ap->num_segments;
  172. envir = &ap->arena_data;
  173. op=sp=envir;
  174. while (*sp) {
  175.     strlength = strlen(sp)+1;
  176.     if ( *(sp+symb_len)=='='  &&
  177.          strnicmp(sp,symbol,symb_len)==0 )
  178.         found=1;
  179.     else {
  180.         needed_size += strlength;
  181.         if (found) strcpy(op,sp);
  182.         op = &op[strlength];
  183.     }
  184.     sp += strlength;
  185. }
  186. *op=0;
  187. if (strlen(val) > 0) {
  188.     needed_size += 3 + strlen(symbol) + strlen(val);
  189.     if (needed_size > total_size)
  190.         return(1);  /* could mess with environment expansion here */
  191.  
  192.     strcpy(op, symbol); strcat(op, "="); strcat(op, val);
  193.     op += strlen(op)+1;
  194.     *op = 0;
  195. }
  196. return(0);
  197. } /* end setheenv subroutine */
  198.